'''
Created on May 23, 2012

@author: tel
'''
import numpy as np
import scipy.stats as ss
import scipy as sp
from scipy import optimize

class Parameter:
    def __init__(self, value):
        self.value = value

    def set(self, value):
        self.value = value

    def __call__(self):
        return self.value

def fit(function, parameters, y, x = None):
    def f(params):
        i = 0
        for p in parameters:
            p.set(params[i])
            i += 1
        return y - function(x)

    if x is None: x = arange(y.shape[0])
    p = [param() for param in parameters]
    optimize.leastsq(f, p, maxfev = 100000)

def fitxy(function, parameters, y, x = None):
    def f(params):
        i = 0
        for p in parameters:
            p.set(params[i])
            i += 1
        return y - function(x)

    if x is None: x = arange(y.shape[0])
    p = [param() for param in parameters]
    optimize.leastsq(f, p, maxfev = 100000)


def gamma_fitter(xdata, ydata):
    a = Parameter(2.)
    t = Parameter(3.3)
    l = Parameter(-5.)
    def fitfunc(x): return ((x-l())**(a()-1)*np.exp(-(x-l())/t()))/  \
                           (sp.special.gamma(a())*(t()**a()))
    
    fit(fitfunc, [a, t, l], ydata, xdata)
    return (a.value, t.value, l.value)

def fit_gamma(data, rang):
    result = {}
    histy, histx = np.histogram(data, bins=30)
    count = histy.sum()
    histy = np.true_divide(histy, count)
    print '{',
    for xval, yval in zip(histx[:-2], histy[:-1]):
        print "{%.16f,%.16f}," % (xval, yval),
    print "{%.16f,%.16f}" % (histx[-2], histy[-1]),
    print'}'
    
    shape, loc, scale  = ss.gamma.fit([histx[:-1], histy], 50, loc=-50, scale=1)
    result['shape'] = shape
    result['scale'] = scale
    result['loc'] = loc
    result['count'] = count
    print result
    return result

